import {Injectable} from "@angular/core";

declare var $:any;

@Injectable()
export class TreeUtil {

  /**
   * 搜索树，高亮显示并展示【模糊匹配搜索条件的节点s】
   * @param treeId                zTree树id
   * @param searchConditionId     搜索节点名
   * @param flag                  需要高亮显示的节点标识
   */
  searchTreeNode(treeId:any, searchCondition:any) {
    //1.得到模糊匹配搜索条件的节点数组集合
    let highlightNodes: Array<string> = [];
    if (searchCondition != "") {
      let treeObj = $.fn.zTree.getZTreeObj(treeId);
      highlightNodes = treeObj.getNodesByParamFuzzy("name", searchCondition, null)
    }
    //2.高亮显示并展示
    this.highlightAndExpand_ztree(treeId, highlightNodes);
  }

  /**
   * 高亮显示并展示【指定节点s】
   * @param treeId
   * @param highlightNodes 需要高亮显示的节点数组
   * @param flag           需要高亮显示的节点标识
   */
  private highlightAndExpand_ztree(treeId:any, highlightNodes:any) {
    let treeObj = $.fn.zTree.getZTreeObj(treeId);
    //1. 先把全部节点更新为普通样式
    let treeNodes = treeObj.transformToArray(treeObj.getNodes());
    for (let i = 0; i < treeNodes.length; i++) {
      if (!!treeNodes[i].highlight) {
        let treeNode = treeNodes[i];
        treeNode.highlight = false;
        treeObj.updateNode(treeNode);
      }
    }

    //2.折叠所有节点
    treeObj.expandAll(false);

    setTimeout(() => {
      if (highlightNodes.length != 0) {
        for (let i = highlightNodes.length - 1; i >= 0; i--) {
          let highlightNode = highlightNodes[i];
          //3.高亮显示节点
          highlightNode.highlight = true;
          treeObj.updateNode(highlightNode);
          let parentNode = highlightNode.getParentNode();
          //3.当前节点的展开
          treeObj.expandNode(parentNode, true, false, true);
        }
      }
    }, 500);
  }

  /**
   * 过滤子节点转化成标准树
   * @param rootNode
   * @param data
   * @returns {any[]}
   */
  filterNodes(rootNode:any,data:any[]):any[]{
    return [].concat(this.recursiveAndConnectChild(rootNode,data));
  }

  /**
   * wrap to Standard Tree
   * @param data
   * @returns {any}
   */
  wrapToStandard(data:any[]):any[]{
    return [].concat(this.recursiveAndConnectChild(null,data));
  }
  /**
   * recursive array and connect parentNode with  childNodes
   * create property "children" to connect childNodes
   * @param parentNode
   * @param otherNodes
   * @returns {any}
   */
  private recursiveAndConnectChild(parentNode:any,otherNodes:any[]):any|any[]{
    let id:any = null;
    if(!!parentNode){
      id = parentNode.id;
    }
    let childNodes = [];
    if(!!otherNodes && otherNodes.length > 0){
      childNodes = otherNodes.filter(function(node){
        if(!!node){
          if(id == (node.pId ? node.pId : null )){
            this.recursiveAndConnectChild(node,otherNodes);
            return true;
          }
        }
        return false;
      },this);
    }

    if(!!parentNode && childNodes.length > 0 ){
      if(!!!parentNode.children){
        parentNode.children = [];
      }
      parentNode.children = parentNode.children.concat(childNodes);
      return parentNode;
    }
    return childNodes;
  }



  /**
   * 基于jquery.ztree.all-3.5.min.js封装的工具类
   * 方法：1.初始化树
   * 		2.添加节点
   * 		3.修改节点
   * 		4.移除节点
   * @author duqunxing
   * @createdate 2013年12月26日 下午9:42:57
   */

  /**
   * 初始化树
   * @param treeId 初始化树的Id
   * @param setting 初始化设置
   * 形如：
   * 	<pre>{
			data: {
				simpleData: {
					enable: true
				},
				keep: {
					parent: true,
					leaf: true
				}
			},
			check: {
				enable: true,
				chkStyle: "radio",
				radioType:"all"
			},
			callback: {
				onCheck: null,
				onClick: null
			}

		}
   * </pre>
   * @param nodes 初始化数据
   */
  init(treeId:any,setting:any,nodes:any){
   return $.fn.zTree.init($("#"+treeId),setting, nodes);
  };
  /**
   * 增加节点
   * @param treeId
   * @param node
   * 形如：<pre>{ id:0201, pId:02, name:"员工考核",href:''}</pre>
   */
  addNode(target:any,node:any){
    let zTree = this.getZTreeObj(target);
    let parentNodes = zTree.getCheckedNodes(true);
    let parentNode=null;
    if(parentNodes.length>0){
      parentNode = parentNodes[0];
    }
    zTree.addNodes(parentNode,node);
  };
  /**
   * 修改节点
   * @param treeId
   * @param node
   * 形如：<pre>{ id:0201, pId:02, name:"员工考核",href:''}</pre>
   */
  updateNode(target:any,node:any){
    let zTree = this.getZTreeObj(target);
    let parentNodes = zTree.getCheckedNodes(true);
    let parentNode=null;
    if(parentNodes.length>0){
      parentNode = parentNodes[0];
    }
    let oldNode = zTree.getNodeByParam("id", node.id, parentNode);
    oldNode.name=node.name;
    zTree.updateNode(oldNode);
  };
  /**
   * 移除节点
   * @param treeId
   * @param nodes
   * 形如：<pre>{ ids:“0201,0202,0203”}</pre>
   */
  removeNodes(target:any,nodes:any){
    let zTree = this.getZTreeObj(target);
    let ids = nodes.ids.split(",");
    let nodeArr = zTree.getNodesByFilter((node:any) => {
      return  ids.indexOf(node.id) > -1;
    },false,null);
    for(let x in nodeArr){
      zTree.removeNode(nodeArr[x]);
    }

  };

  /**
   * 移除选中节点中第一个节点的下对应子节点
   * @param target
   * @param nodes
   */
  removeChildsByChecked(target:any,nodes:any){
    let zTree = this.getZTreeObj(target);
    let ids = nodes.ids.split(",");
    let parentNodes = zTree.getCheckedNodes(true);
    let parentNode=null;
    if(parentNodes.length>0){
      parentNode = parentNodes[0];
    }
    for(var i=0;i<ids.length;i++){
      let oldNode = zTree.getNodeByParam("id", ids[i], parentNode);
      zTree.removeNode(oldNode);
    }
  }

  getZTreeObj(target:any){
    let _treeId = $(target).attr('id');
    return $.fn.zTree.getZTreeObj(_treeId);
  }


  oneTree(treeId:any,options:any, param:any) {
    let _opts = $.extend({}, this.defaults, options);
    return this.init(treeId, _opts, param);
  }


  private defaults = {
    data: {
      simpleData: {
        enable : true,
        idKey : "id",
        pIdKey : "pId",
        rootPId : 0
        // rooPId : null
      },
      keep: {
        parent : false,
        leaf : false
      },
      key:{
        checked : "checked",
        children : "children",
        name : "name",
        title : "",
        url : "xurl"
      }
    },
    check: {
      enable: false
    },
    callback: {
      onCheck: function () {

      },
      onClick: function () {

      }
    }
  }





}
